package com.zmn.plat.business.impl.netcall;

import java.security.MessageDigest;
import java.util.*;

import javax.annotation.Resource;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.zmn.common.utils.number.RandomUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.plat.business.interfaces.netcall.UserImAccountBService;
import com.zmn.plat.constant.ImConstant;
import com.zmn.plat.model.entity.netcall.UserImAccount;
import com.zmn.plat.services.interfaces.netcall.UserImAccountService;

/**
 * @author sunlife
 * @since 2019/7/11 20:08
 */
@Service
public class UserImAccountBServiceImpl implements UserImAccountBService {

    private Logger logger = LoggerFactory.getLogger(UserImAccountBServiceImpl.class);

    @Resource
    private UserImAccountService userImAccountService;

    /**
     * 根据用户ID获取网易云账户信息
     * 
     * @param staffId
     * @return
     */
    @Override
    public UserImAccount getAccountByStaffId(Integer staffId) {
        UserImAccount account = userImAccountService.selectByStaffId(staffId);
        // 当前未注册过网易云信ID
        if (Objects.isNull(account)) {
            account = new UserImAccount();
            account.setStaffId(staffId);
            String imAcctId = RandomUtil.getStringRandom(32).toLowerCase();
            account.setImAcctId(imAcctId);
            String token = getTokenFromIM(imAcctId);
            account.setImToken(token);
            if (StringUtil.isNotBlank(token)) {
                userImAccountService.insert(account);
            } else {
                throw new RuntimeException("网易云信接口调用失败");
            }
        }
        return account;
    }

    /**
     * 根据用户ID禁用网易云ID
     * 
     * @param staffId
     * @return
     */
    @Override
    public boolean blockAccountByStaffId(Integer staffId) {
        UserImAccount account = userImAccountService.selectByStaffId(staffId);
        if (!Objects.isNull(account)) {
            return this.blockImAcct(ImConstant.BLOCK, account.getImAcctId());
        }
        return true;
    }

    /**
     * 解禁网易云ID
     * 
     * @param staffId
     * @return
     */
    @Override
    public boolean unblockAccountByStaffId(Integer staffId) {
        UserImAccount account = userImAccountService.selectByStaffId(staffId);
        if (!Objects.isNull(account)) {
            return this.blockImAcct(ImConstant.UNBLOCK, account.getImAcctId());
        }
        return false;
    }

    /**
     * 更新用户名
     * 
     * @param staffId
     * @param name
     * @return
     */
    @Override
    public boolean updateAcctName(Integer staffId, String name) {
        UserImAccount account = userImAccountService.selectByStaffId(staffId);
        if (!Objects.isNull(account)) {
            return this.updateAcctName(account.getImAcctId(), name);
        }
        return false;
    }

    // 禁用/解禁网易云接口
    private boolean blockImAcct(Integer status, String imAcctId) {
        String url;
        if (Objects.equals(status, ImConstant.BLOCK)) {
            url = ImConstant.BLOCK_URL;
        } else {
            url = ImConstant.UNBLOCK_URL;
        }
        List<NameValuePair> nvps = new ArrayList<>();
        nvps.add(new BasicNameValuePair("accid", imAcctId));
        JSONObject result = requestIM(url, nvps);
        if (!Objects.isNull(result) && Objects.equals(result.getString("code"), "200")) {
            return true;
        } else {
            return false;
        }
    }

    // 更新用户信息
    private Boolean updateAcctName(String imAcctId, String name) {
        List<NameValuePair> nvps = new ArrayList<>();
        nvps.add(new BasicNameValuePair("accid", imAcctId));
        nvps.add(new BasicNameValuePair("name", name));
        JSONObject result = requestIM(ImConstant.UPDATEINFO_URL, nvps);
        if (!Objects.isNull(result) && Objects.equals(result.getString("code"), "200")) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 请求token
     * 
     * @param imAcctId
     * @return
     */
    private String getTokenFromIM(String imAcctId) {
        List<NameValuePair> nvps = new ArrayList<>();
        nvps.add(new BasicNameValuePair("accid", imAcctId));
        JSONObject result = requestIM(ImConstant.CREATE_URL, nvps);
        if (!Objects.isNull(result) && Objects.equals(result.getString("code"), "200")) {
            return result.getJSONObject("info").getString("token");
        } else {
            return "";
        }
    }

    private JSONObject requestIM(String url, List<NameValuePair> nvps) {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        String appKey = ImConstant.APPKEY;
        String appSecret = ImConstant.APPSECRET;
        String nonce = UUID.randomUUID().toString();
        String curTime = String.valueOf((new Date()).getTime() / 1000L);
        String checkSum = getCheckSum(appSecret, nonce, curTime);// 参考 计算CheckSum的java代码

        // 设置请求的header
        httpPost.addHeader("AppKey", appKey);
        httpPost.addHeader("Nonce", nonce);
        httpPost.addHeader("CurTime", curTime);
        httpPost.addHeader("CheckSum", checkSum);
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

        try {
            // 设置请求的参数
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));

            // 执行请求
            HttpResponse response = httpClient.execute(httpPost);

            String entity = EntityUtils.toString(response.getEntity(), "utf-8");

            // 打印执行结果
            JSONObject result = JSONObject.parseObject(entity);
            return result;
        } catch (Exception e) {
            logger.info("获取token失败" + e.getMessage());
        }
        return null;
    }

    // 计算并获取CheckSum
    private String getCheckSum(String appSecret, String nonce, String curTime) {
        return encode("sha1", appSecret + nonce + curTime);
    }

    // 计算并获取md5值
    private String getMD5(String requestBody) {
        return encode("md5", requestBody);
    }

    private String encode(String algorithm, String value) {
        if (value == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
            messageDigest.update(value.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
}
